package com.kinsin.kinsinutils

import android.app.Activity
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding

/**
 * 基类Activity
 *
 * 备选方案：通过反射来实现基类，可以做到子类无需任何操作即可使用binding，但是缺点也很多
 * abstract class BaseActivity<VB : ViewBinding> : Activity() {
 *     protected lateinit var binding: VB
 *
 *     override fun onCreate(savedInstanceState: Bundle?) {
 *         super.onCreate(savedInstanceState)
 *         // 通过反射获取 ViewBinding 的 inflate 方法
 *         val inflateMethod = VB::class.java.getMethod("inflate", LayoutInflater::class.java)
 *         // 调用静态方法生成 Binding 实例
 *         binding = inflateMethod.invoke(null, layoutInflater) as VB
 *         // 设置 ContentView
 *         setContentView(binding.root)
 *     }
 * }
 * 这个方案需要混淆：
 * -keepclassmembers class * implements androidx.viewbinding.ViewBinding {
 *     public static ​**​ inflate(android.view.LayoutInflater);
 * }
 *
 *
 * 下面是反射方案的缺点：
 * 为什么业务开发要尽量避免反射？
 * 1. 性能隐患（虽然现代设备不明显）
 * 反射原理：反射是通过运行时动态查找类、方法等信息，比直接调用代码要慢。虽然现代 Android 优化后差异不大，但在低端设备或复杂场景中可能成为性能瓶颈。
 * 举例：假设你的 BaseActivity 被 100 个 Activity 继承，每次反射调用 inflate 方法时，虽然单次耗时只有几毫秒，但积少成多可能影响启动速度。
 * 2. 代码可读性和维护性
 * 隐藏的“魔法”：反射代码看起来像“黑箱”（比如 getMethod("inflate", ...)），其他开发者需要花时间理解反射逻辑，而直接调用 ActivityMainBinding.inflate() 则一目了然。
 * 重构风险：如果你重命名了某个 Binding 类的方法名（比如 inflate 改为 create），反射代码会在运行时直接崩溃，而直接调用会在编译时报错，提前发现问题。
 * 3. ProGuard 混淆的坑
 * 反射的“天敌”：发布正式包时，ProGuard/R8 会混淆代码（比如把 ActivityMainBinding 类名改成 a）。如果忘记配置混淆规则，反射代码会因找不到类或方法而崩溃。
 * 手动初始化无此问题：直接调用 ActivityMainBinding.inflate() 时，ProGuard 会自动识别并保留必要的方法，无需额外配置。
 * 4. IDE 支持的局限性
 * 代码提示失效：反射调用的方法名（如 "inflate"）是字符串形式，IDE 无法提供自动补全或错误检查，容易拼写错误。
 * 直接调用有智能提示：输入 ActivityMainBinding. 时，IDE 会直接提示 inflate() 方法，减少出错可能。
 *
 */
abstract class BaseActivity<VB : ViewBinding>(
    private val inflateBinding: (LayoutInflater) -> VB
) : Activity() {
    protected lateinit var binding: VB

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.i("AppManagerViewModel", "onCreate0: ")
        binding = inflateBinding(layoutInflater)
        setContentView(binding.root)
        initFirst()
        initData()
        initAction()
    }

    /**
     * 最早的方法
     */
    abstract fun initFirst()

    abstract fun initData()

    abstract fun initAction()
}

abstract class BaseAppCompatActivity<VB : ViewBinding>(
    private val inflateBinding: (LayoutInflater) -> VB
) : AppCompatActivity() {
    protected lateinit var binding: VB

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.i("AppManagerViewModel", "onCreate0: ")
        binding = inflateBinding(layoutInflater)
        setContentView(binding.root)
        initFirst()
        initData()
        initAction()
    }

    /**
     * 最早的方法
     */
    abstract fun initFirst()

    abstract fun initData()

    abstract fun initAction()
}